#pragma once
#include "basetypes.h"
#include <list>

/*
Basic Math Stuffs
we are going to duplicate a lot of math functionality, so we need to aggregate them.
someone have built a class with static members, someone else a singleton, 
someone else a set of free functions and someone else a namespace with free functions.

I'm taking the decision (but this is arguable, and I'd like to listen to your opinions) 
to design the Basic Math Utils collection as a set of free functions (and maybe some class if we'll need)
under a namespace to avoid spamming on the global namespace, because our project is becoming big enough.

This is not a professional project, our main goals are learn c++, learn how to design code and how to develop 
code with others, so we can allow ourself to be redundant for a while and keep multiple "function candidates"
for each task, until we "elect" a killer one and we'll maintain only that!

So I'll cut copy in your local projects and paste here, maybe reformatted and cleaned, but actually your code.
We'll analyze performances of different implementations and than the losers will be pruned off.

In future, avoid putting Math Code in your local projects, put them here so anyone can use them!
*/

namespace math
{
    typedef std::pair<UInt, UInt> FactorExp;
    typedef std::list<FactorExp> FactorExpList;
    typedef FactorExpList::iterator FactorExpIterator;

	bool IsOdd(const UInt i_number);

	/*
	Prime numbers:
	there's a plenty of implementations, all very similar but someone is so strange I'd like to comment
	1) the input parameter (const or not const? int or uint? 
	   32, 64 or builtin? by value or by reference?)
	2) the oddity check (should we check if the number is not odd, for an eary exit?)
	3) i <= sqrt(num) or i*i<num ? first one is better for numbers bigger than an unknown threshold.
	and other small stuff... I keep almost all of them but we are going to expose just a single one in the library.
	I think it's better to expose a "const UInt i_number" that performs an oddity check and use sqrt.
	In general, it's more efficient to pass basic types by const value than by const&. And it applies also for 64bit integers
	p.s. special note to MauroBordin that implemented a particular algorithm!
	*/
	//bool IsPrime(const UInt64& number); //AlbertoDestro
	//bool IsPrime(const int& number); //AndreaMugnaini
	//bool IsPrime(const UInt64 number); //GiorgioUgazio & LucaGiona & MauroBordin
	//bool IsPrime(const UInt32 number); //FilippoFantini & MartinoGiovannelli
	bool IsPrime(const UInt i_number); // A merge...

	/*
	Palindrome: same as prime numbers: a lot of implementations, I choose this one but a little bit modified.
	*/
	bool IsPalindrome(const UInt i_number); //cheated from AlbertoDestro

	/* 
	MCD and MCM: I choose to implement the UInt version, if we'll need a UInt64 version we'll see how to do it:
	we can template it or write specific overloads that take two UInt64 and return a UInt64.
	*/
	UInt GetMCM(const UInt i_first, const UInt i_second);

	template<typename Container>
	UInt GetMCM(const Container& i_container);

	UInt GetMCD(const UInt i_first, const UInt i_second);

	template<typename Container>
	UInt GetMCD(const Container& i_container);

	UInt GetNumberOfDivisors(const UInt i_number);

	void ComputePrimeFactors(const UInt64 i_number, FactorExpList& o_factorList);
}

//function definitions
#include "MathUtils.inl"